Codeforces Round 349 (Div. 2) C. Reberland Linguistics(dp)
题意:
$给定5\le |L|\le 10^4长度的字符串,现划分这个字符串$
$使得第一个子串长度\ge 5,后面的所有子串长度为2或3,并且相邻的2个子串不能相同
$
$字典序输出所有划分方案中的长度为2或3的子串$
分析:
$- - 当然是dp啦,f[i][0]:=前i个字符,划分长度2的合法子串,s[i-1,i]$
$同理,f[i][1]:=前i个字符,划分长度3的合法子串,s[i-2,i-1,i]$
$这个dp是顺着的,我们发现没法保证中途的合法性,不能存储这些子串$
$但是倒着dp就可以了,就都是合法的了,就可以边搞边存了$
代码:
//
// Created by TaoSama on 2016-04-30
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
string s;
int f[N][2];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> s) {
memset(f, 0, sizeof f);
s = ' ' + s;
int sz = s.size() - 1;
set<string> ss;
for(int i = sz, j = 1; i; --i, ++j) {
if(j < 2 || i <= 5) continue;
if(j == 2) {
ss.insert(s.substr(i, 2));
f[i][0] = 1;
} else if(j == 3) {
ss.insert(s.substr(i, 3));
f[i][1] = 1;
} else {
if(f[i + 2][0]) {
string b = s.substr(i + 2, 2);
string c = s.substr(i, 2);
if(b != c) {
ss.insert(c);
f[i][0] = 1;
}
}
if(f[i + 2][1]) {
string c = s.substr(i, 2);
ss.insert(c);
f[i][0] = 1;
}
if(f[i + 3][0]) {
string c = s.substr(i, 3);
ss.insert(c);
f[i][1] = 1;
}
if(f[i + 3][1]) {
string b = s.substr(i + 3, 3);
string c = s.substr(i, 3);
if(b != c) {
ss.insert(c);
f[i][1] = 1;
}
}
}
}
cout << ss.size() << '\n';
for(auto s : ss) cout << s << '\n';
}
return 0;
}